package org.convallaria.infrastruct.db.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 企业级线程池管理器
 * 
 * 功能特性：
 * - 统一的线程池创建和管理
 * - 线程池监控和统计
 * - 自定义线程工厂和拒绝策略
 * - 优雅关闭和资源清理
 * - 线程池健康检查
 * 
 * @author gjh
 * @since 2024-09-24
 */
@Slf4j
public class ThreadPoolManager {

    // 线程池注册表
    private static final Map<String, ManagedThreadPool> threadPools = new ConcurrentHashMap<>();
    
    // 全局统计
    private static final AtomicLong totalCreatedPools = new AtomicLong(0);
    private static final AtomicLong totalDestroyedPools = new AtomicLong(0);
    
    // 关闭钩子标记
    private static volatile boolean shutdownHookRegistered = false;

    /**
     * 托管线程池包装器
     */
    public static class ManagedThreadPool {
        private final String name;
        private final ExecutorService executor;
        private final ThreadPoolExecutor threadPoolExecutor; // 用于监控
        private final LocalDateTime createTime;
        private volatile LocalDateTime lastActivityTime;
        private final AtomicLong completedTasks = new AtomicLong(0);
        private final AtomicLong rejectedTasks = new AtomicLong(0);

        public ManagedThreadPool(String name, ExecutorService executor) {
            this.name = name;
            this.executor = executor;
            this.threadPoolExecutor = (executor instanceof ThreadPoolExecutor) ? 
                (ThreadPoolExecutor) executor : null;
            this.createTime = LocalDateTime.now();
            this.lastActivityTime = LocalDateTime.now();
        }

        public ExecutorService getExecutor() {
            lastActivityTime = LocalDateTime.now();
            return executor;
        }

        public String getName() { return name; }
        public LocalDateTime getCreateTime() { return createTime; }
        public LocalDateTime getLastActivityTime() { return lastActivityTime; }
        
        public boolean isTerminated() {
            return executor.isTerminated();
        }

        public boolean isShutdown() {
            return executor.isShutdown();
        }

        /**
         * 获取线程池统计信息
         */
        public String getStatistics() {
            if (threadPoolExecutor == null) {
                return String.format("线程池 [%s] - 基础执行器，无详细统计", name);
            }

            return String.format(
                "线程池 [%s] - 核心线程: %d, 最大线程: %d, 活跃线程: %d, " +
                "队列大小: %d, 已完成任务: %d, 总任务数: %d, 拒绝任务: %d",
                name,
                threadPoolExecutor.getCorePoolSize(),
                threadPoolExecutor.getMaximumPoolSize(),
                threadPoolExecutor.getActiveCount(),
                threadPoolExecutor.getQueue().size(),
                threadPoolExecutor.getCompletedTaskCount(),
                threadPoolExecutor.getTaskCount(),
                rejectedTasks.get()
            );
        }

        /**
         * 关闭线程池
         */
        public void shutdown() {
            try {
                executor.shutdown();
                if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
                    log.warn("线程池 [{}] 未能在10秒内正常关闭，强制关闭", name);
                    executor.shutdownNow();
                    
                    if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                        log.error("线程池 [{}] 强制关闭失败", name);
                    }
                }
                log.info("线程池 [{}] 已成功关闭", name);
            } catch (InterruptedException e) {
                log.warn("关闭线程池 [{}] 时被中断", name);
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

    /**
     * 自定义线程工厂
     */
    public static class CustomThreadFactory implements ThreadFactory {
        private final String namePrefix;
        private final boolean daemon;
        private final AtomicLong threadCount = new AtomicLong(0);
        private final ThreadGroup threadGroup;

        public CustomThreadFactory(String namePrefix, boolean daemon) {
            this.namePrefix = namePrefix;
            this.daemon = daemon;
            this.threadGroup = new ThreadGroup(namePrefix + "-group");
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(threadGroup, r, 
                namePrefix + "-" + threadCount.incrementAndGet());
            thread.setDaemon(daemon);
            thread.setPriority(Thread.NORM_PRIORITY);
            
            // 设置未捕获异常处理器
            thread.setUncaughtExceptionHandler((t, e) -> 
                log.error("线程 [{}] 发生未捕获异常", t.getName(), e));
                
            return thread;
        }
    }

    /**
     * 自定义拒绝策略
     */
    public static class LoggingRejectedExecutionHandler implements RejectedExecutionHandler {
        private final String poolName;

        public LoggingRejectedExecutionHandler(String poolName) {
            this.poolName = poolName;
        }

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            log.warn("线程池 [{}] 拒绝执行任务: {}, 活跃线程: {}, 队列大小: {}", 
                poolName, r.getClass().getSimpleName(), 
                executor.getActiveCount(), executor.getQueue().size());
                
            // 更新拒绝任务统计
            ManagedThreadPool pool = threadPools.get(poolName);
            if (pool != null) {
                pool.rejectedTasks.incrementAndGet();
            }
            
            // 默认行为：在调用线程中执行
            if (!executor.isShutdown()) {
                r.run();
            }
        }
    }

    /**
     * 创建固定大小线程池
     */
    public static ExecutorService createFixedThreadPool(String name, int nThreads) {
        return createFixedThreadPool(name, nThreads, true);
    }

    public static ExecutorService createFixedThreadPool(String name, int nThreads, boolean daemon) {
        validatePoolName(name);
        
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            nThreads, nThreads,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(),
            new CustomThreadFactory(name, daemon),
            new LoggingRejectedExecutionHandler(name)
        );
        
        return registerPool(name, executor);
    }

    /**
     * 创建可缓存线程池
     */
    public static ExecutorService createCachedThreadPool(String name) {
        return createCachedThreadPool(name, true);
    }

    public static ExecutorService createCachedThreadPool(String name, boolean daemon) {
        validatePoolName(name);
        
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            0, Integer.MAX_VALUE,
            60L, TimeUnit.SECONDS,
            new SynchronousQueue<>(),
            new CustomThreadFactory(name, daemon),
            new LoggingRejectedExecutionHandler(name)
        );
        
        return registerPool(name, executor);
    }

    /**
     * 创建单线程执行器
     */
    public static ExecutorService createSingleThreadExecutor(String name) {
        return createSingleThreadExecutor(name, true);
    }

    public static ExecutorService createSingleThreadExecutor(String name, boolean daemon) {
        validatePoolName(name);
        
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            1, 1,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(),
            new CustomThreadFactory(name, daemon),
            new LoggingRejectedExecutionHandler(name)
        );
        
        return registerPool(name, executor);
    }

    /**
     * 创建单线程调度执行器
     */
    public static ScheduledExecutorService createSingleThreadScheduledExecutor(String name) {
        return createSingleThreadScheduledExecutor(name, true);
    }

    public static ScheduledExecutorService createSingleThreadScheduledExecutor(String name, boolean daemon) {
        validatePoolName(name);
        
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(
            1,
            new CustomThreadFactory(name, daemon),
            new LoggingRejectedExecutionHandler(name)
        );
        
        // 设置策略：任务完成后从队列中移除
        executor.setRemoveOnCancelPolicy(true);
        
        registerPool(name, executor);
        return executor;
    }

    /**
     * 创建调度线程池
     */
    public static ScheduledExecutorService createScheduledThreadPool(String name, int corePoolSize) {
        return createScheduledThreadPool(name, corePoolSize, true);
    }

    public static ScheduledExecutorService createScheduledThreadPool(String name, int corePoolSize, boolean daemon) {
        validatePoolName(name);
        
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(
            corePoolSize,
            new CustomThreadFactory(name, daemon),
            new LoggingRejectedExecutionHandler(name)
        );
        
        executor.setRemoveOnCancelPolicy(true);
        
        registerPool(name, executor);
        return executor;
    }

    /**
     * 创建自定义线程池
     */
    public static ExecutorService createCustomThreadPool(String name, 
                                                        int corePoolSize,
                                                        int maximumPoolSize,
                                                        long keepAliveTime,
                                                        TimeUnit unit,
                                                        BlockingQueue<Runnable> workQueue) {
        return createCustomThreadPool(name, corePoolSize, maximumPoolSize, 
            keepAliveTime, unit, workQueue, true);
    }

    public static ExecutorService createCustomThreadPool(String name, 
                                                        int corePoolSize,
                                                        int maximumPoolSize,
                                                        long keepAliveTime,
                                                        TimeUnit unit,
                                                        BlockingQueue<Runnable> workQueue,
                                                        boolean daemon) {
        validatePoolName(name);
        
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            corePoolSize, maximumPoolSize,
            keepAliveTime, unit,
            workQueue,
            new CustomThreadFactory(name, daemon),
            new LoggingRejectedExecutionHandler(name)
        );
        
        return registerPool(name, executor);
    }

    /**
     * 验证线程池名称
     */
    private static void validatePoolName(String name) {
        if (!StringUtils.hasText(name)) {
            throw new IllegalArgumentException("线程池名称不能为空");
        }
        if (threadPools.containsKey(name)) {
            throw new IllegalArgumentException("线程池名称已存在: " + name);
        }
    }

    /**
     * 注册线程池
     */
    private static ExecutorService registerPool(String name, ExecutorService executor) {
        ManagedThreadPool managedPool = new ManagedThreadPool(name, executor);
        threadPools.put(name, managedPool);
        totalCreatedPools.incrementAndGet();
        
        log.info("线程池 [{}] 已创建并注册", name);
        
        // 注册关闭钩子
        registerShutdownHook();
        
        return executor;
    }

    /**
     * 获取线程池
     */
    public static ExecutorService getThreadPool(String name) {
        ManagedThreadPool pool = threadPools.get(name);
        return pool != null ? pool.getExecutor() : null;
    }

    /**
     * 获取调度线程池
     */
    public static ScheduledExecutorService getScheduledThreadPool(String name) {
        ExecutorService executor = getThreadPool(name);
        if (executor instanceof ScheduledExecutorService) {
            return (ScheduledExecutorService) executor;
        }
        return null;
    }

    /**
     * 关闭指定线程池
     */
    public static void shutdownPool(String name) {
        ManagedThreadPool pool = threadPools.remove(name);
        if (pool != null) {
            pool.shutdown();
            totalDestroyedPools.incrementAndGet();
        }
    }

    /**
     * 关闭所有线程池
     */
    public static void shutdownAll() {
        log.info("开始关闭所有线程池，当前线程池数量: {}", threadPools.size());
        
        for (Map.Entry<String, ManagedThreadPool> entry : threadPools.entrySet()) {
            try {
                entry.getValue().shutdown();
                totalDestroyedPools.incrementAndGet();
            } catch (Exception e) {
                log.error("关闭线程池 [{}] 时发生异常", entry.getKey(), e);
            }
        }
        
        threadPools.clear();
        log.info("所有线程池已关闭");
    }

    /**
     * 获取线程池统计报告
     */
    public static String getStatisticsReport() {
        StringBuilder report = new StringBuilder();
        report.append("\n=== 线程池管理器统计报告 ===\n");
        report.append("总创建线程池数: ").append(totalCreatedPools.get()).append("\n");
        report.append("总销毁线程池数: ").append(totalDestroyedPools.get()).append("\n");
        report.append("当前活跃线程池数: ").append(threadPools.size()).append("\n\n");
        
        if (threadPools.isEmpty()) {
            report.append("当前无活跃线程池\n");
        } else {
            report.append("=== 活跃线程池详情 ===\n");
            threadPools.values().forEach(pool -> {
                report.append(pool.getStatistics()).append("\n");
                report.append("创建时间: ").append(pool.getCreateTime()).append("\n");
                report.append("最后活跃时间: ").append(pool.getLastActivityTime()).append("\n\n");
            });
        }
        
        return report.toString();
    }

    /**
     * 健康检查
     */
    public static boolean healthCheck() {
        try {
            for (ManagedThreadPool pool : threadPools.values()) {
                if (pool.isTerminated()) {
                    log.warn("发现已终止的线程池: {}", pool.getName());
                    return false;
                }
            }
            return true;
        } catch (Exception e) {
            log.error("线程池健康检查失败", e);
            return false;
        }
    }

    /**
     * 注册关闭钩子
     */
    private static void registerShutdownHook() {
        if (!shutdownHookRegistered) {
            synchronized (ThreadPoolManager.class) {
                if (!shutdownHookRegistered) {
                    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                        log.info("JVM关闭中，正在清理线程池资源...");
                        shutdownAll();
                    }, "ThreadPoolManager-ShutdownHook"));
                    shutdownHookRegistered = true;
                    log.debug("线程池关闭钩子已注册");
                }
            }
        }
    }

    // ===== 便捷方法 =====

    /**
     * 检查线程池是否存在
     */
    public static boolean exists(String name) {
        return threadPools.containsKey(name);
    }

    /**
     * 获取线程池数量
     */
    public static int getPoolCount() {
        return threadPools.size();
    }

    /**
     * 获取所有线程池名称
     */
    public static String[] getPoolNames() {
        return threadPools.keySet().toArray(new String[0]);
    }
}
